package com.uzhie.jt808;

import com.uzhie.jt808.msg.JT808MsgBean;
import com.uzhie.jt808.util.JT808ProtocolUtil;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

/**
 * Created by Coder on 2018/7/6.
 * 808 协议服务请求处理器
 */
@ChannelHandler.Sharable
public class JT808MsgChannelInHandler extends ChannelInboundHandlerAdapter {

    private Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    @Qualifier(value = "jt808Dispatcher")
    private JT808Dispatcher dispatcher;

    @Autowired
    @Qualifier(value = "sessionManager")
    protected JT808SessionManager sessionManager;

    // 当前线程的请求消息
    private JT808MsgBean currentReqMsg;
    // 当前线程的响应消息
    private JT808MsgBean currentResMsg;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        logger.trace("enter method channelRegistered");
//        JT808ChannelHandlerContextHolder.setContextThreadLocal(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        logger.trace("enter method channelUnregistered");
//        JT808ChannelHandlerContextHolder.removeContextThreadLocal();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.trace("enter method channelActive:" + ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.trace("enter method channelInactive:" + ctx);
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        logger.trace("enter method channelRead ");
        currentReqMsg = (JT808MsgBean) msg;
        if (currentReqMsg.getCheckCode() == -1) {
            throw new IllegalArgumentException("校验码错误！");
        }
        currentReqMsg.setChannelHandlerContext(ctx);
        // 刷新session
        refreshSession();
        // 分发请求
        currentResMsg = dispatcher.dispatch(currentReqMsg);
        ReferenceCountUtil.release(msg);
        ctx.writeAndFlush(currentResMsg);
    }

    /**
     * 这个方法将在通道所有数据被读取完毕后触发
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        logger.trace("enter method channelReadComplete ");
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        logger.trace("enter method userEventTriggered:" + ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("enter method exceptionCaught", cause);
        byte[] bodyBytes = JT808ProtocolUtil.commonRespBodyBytes(currentReqMsg.getHeader().getMsgID(), currentReqMsg.getHeader().getFlowNum(), 1);
        currentResMsg = JT808ProtocolUtil.build808Obj(currentReqMsg.getHeader().getMsgID(), currentReqMsg.getHeader().getFlowNum(), currentReqMsg.getHeader().getSimNum(), bodyBytes);
        ctx.writeAndFlush(currentResMsg);
    }

    private void refreshSession() {
        String channelID = currentReqMsg.getChannelHandlerContext().channel().id().asShortText();
        sessionManager.refreshChannelSimMap(channelID, currentReqMsg.getHeader().getSimNum());
        sessionManager.refreshSimSession(currentReqMsg.getHeader().getSimNum(), currentReqMsg.getChannelHandlerContext().channel());
        logger.debug("JT808MsgChannelInHandler channelID:" + channelID + " 绑定session sim卡号:" + currentReqMsg.getHeader().getSimNum());
    }
}
